home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
dvitovdu32
/
src
/
pascal
/
fontreader.p
< prev
next >
Wrap
Text File
|
1991-11-10
|
30KB
|
898 lines
(* FontReader implements the routines for reading character metric and
bitmap information from PK files, or from TFM files for PostScript fonts.
The metric information accessed by PixelTableRoutine is used by
DVIReader to calculate character positions on a page.
The bitmap information accessed by GetBitmap is used by the
main program to display characters (from non-PostScript fonts).
*)
#include 'globals.h';
#include 'files.h';
#include 'screenio.h';
#include 'vdu.h';
#include 'options.h';
#include 'dvireader.h';
#include 'fontreader.h';
VAR
PTfile : integer; (* PK/TFM file descriptor *)
PToffset : INTEGER; (* current byte offset in PTfile *)
currPTbuff : INTEGER; (* starting byte offset in buffer *)
PTbuffer : buffer; (* input buffer *)
psprefixlen, (* length of psprefix string *)
fontdirlen : INTEGER; (* length of fontdir string *)
gpower : ARRAY [0..32] OF BITSET; (* 0,1,11,111,1111,... *)
turnon : BOOLEAN; (* is current run black? *)
dynf, (* dynamic packing variable *)
repeatcount, (* times to repeat the next row *)
bitweight : INTEGER; (* for bits or nybbles from inputbyte *)
inputbyte : bytes_or_bits; (* the current input byte *)
lf, lh, bc, ec, nw, nh : INTEGER; (* TFM file data *)
TFMinfo : ARRAY [0..255] OF
RECORD
wdindex, htindex, dpindex : INTEGER;
END;
charmetrics : ARRAY [0..255] OF
RECORD
width, height, depth : ARRAY [0..3] OF INTEGER;
END;
(******************************************************************************)
PROCEDURE BuildTFMSpec (fontptr : fontinfoptr);
(* Build a complete TFM file specification in fontptr^.fontspec.
This will only be done once per font; fontspeclen will no longer be 0.
fontptr^.fontexists becomes TRUE if the file can be opened.
*)
LABEL 999;
VAR f, result, i, nxt : INTEGER;
BEGIN
WITH fontptr^ DO BEGIN
i := 0;
IF fontarealen > 0 THEN BEGIN
nxt := fontarealen;
REPEAT
fontspec[i] := fontarea[i]; (* start fontspec with fontarea *)
i := i + 1;
UNTIL (i = nxt) OR (i > maxfontspec);
END
ELSE BEGIN
nxt := Len(tfmdir); (* assume > 0 *)
REPEAT
fontspec[i] := tfmdir[i]; (* start fontspec with tfmdir *)
i := i + 1;
UNTIL (i = nxt) OR (i > maxfontspec);
END;
IF nxt >= maxfontspec THEN BEGIN
fontspeclen := maxfontspec;
goto 999; (* fontspec truncated *)
END;
(* nxt is current length of fontspec; append fontname.tfm *)
i := 0;
WHILE (i < fontnamelen) AND (nxt < maxfontspec) DO BEGIN
fontspec[nxt] := fontname[i]; (* append fontname *)
i := i + 1;
nxt := nxt + 1;
END;
IF nxt + 4 <= maxfontspec THEN BEGIN (* append .tfm *)
fontspec[nxt] := '.'; nxt := nxt + 1;
fontspec[nxt] := 't'; nxt := nxt + 1;
fontspec[nxt] := 'f'; nxt := nxt + 1;
fontspec[nxt] := 'm'; nxt := nxt + 1;
END
ELSE BEGIN
fontspeclen := maxfontspec;
goto 999; (* fontspec truncated *)
END;
fontspeclen := nxt;
IF fontspeclen < maxstring THEN fontspec[fontspeclen] := CHR(0);
f := open(fontspec,O_RDONLY,0); (* try to open file *)
IF fontspeclen < maxstring THEN fontspec[fontspeclen] := ' ';
IF f >= 0 THEN BEGIN
result := close(f);
fontexists := TRUE; (* fontspec exists *)
END;
END;
999:
END; (* BuildTFMSpec *)
(******************************************************************************)
FUNCTION CompleteFontSpec (fontptr : fontinfoptr;
nxt : INTEGER;
fontsizelen : INTEGER;
VAR firstn : INTEGER) : BOOLEAN;
(* Return TRUE if we can append "fontname.n...npk" to fontspec.
Such a scheme is used in the latest TeX distributions.
*)
LABEL 999;
VAR i : INTEGER;
BEGIN
WITH fontptr^ DO BEGIN
i := 0;
WHILE (i < fontnamelen) AND (nxt < maxfontspec) DO BEGIN
fontspec[nxt] := fontname[i]; (* append fontname *)
i := i + 1;
nxt := nxt + 1;
END;
firstn := nxt + 1; (* position of 1st n *)
IF nxt + fontsizelen + 2 < maxfontspec THEN BEGIN
fontspec[nxt] := '.';
nxt := nxt + fontsizelen + 1; (* skip n...n *)
fontspec[nxt] := 'p'; (* append pk *)
nxt := nxt + 1;
fontspec[nxt] := 'k';
nxt := nxt + 1;
END
ELSE BEGIN
fontspeclen := maxfontspec;
CompleteFontSpec := FALSE;
goto 999; (* fontspec truncated *)
END;
fontspeclen := nxt;
IF nxt < maxfontspec THEN fontspec[nxt] := ' '; (* terminate string *)
CompleteFontSpec := TRUE;
END;
999:
END; (* CompleteFontSpec *)
(******************************************************************************)
PROCEDURE BuildFontSpec (fontptr : fontinfoptr);
(* Build a complete file specification in fontptr^.fontspec.
This will only be done once per font; fontspeclen will no longer be 0.
fontptr^.fontexists becomes TRUE if the file can be opened.
*)
LABEL 888, 999;
VAR
f, result, i, j, nxt, fontsize,
firstn, lastn, tempsize, tempsizelen : INTEGER;
BEGIN
WITH fontptr^ DO BEGIN
(* first check for a PostScript font; following code will set psfont to TRUE
if psprefixlen = 0 --- ALL fonts will be considered PostScript fonts
*)
psfont := TRUE;
i := 0;
WHILE TRUE DO BEGIN
IF i = psprefixlen THEN goto 888;
IF Cap(fontname[i]) <> Cap(psprefix[i]) THEN BEGIN
psfont := FALSE;
goto 888;
END;
i := i + 1;
END;
888:
IF psfont THEN BEGIN
BuildTFMSpec(fontptr); (* build TFM file spec *)
goto 999;
END;
i := 0;
nxt := fontdirlen;
REPEAT
fontspec[i] := fontdir[i]; (* start fontspec with fontdir *)
i := i + 1;
UNTIL (i = nxt) OR (i > maxfontspec);
IF nxt >= maxfontspec THEN BEGIN
fontspeclen := maxfontspec;
goto 999; (* fontspec truncated *)
END;
fontsize := TRUNC( mag * (scaledsize / designsize)
* (resolution / 1000.0) + 0.5 );
IF fontsize = 0 THEN
fontsize := fontsize + 1; (* allow for subtracting 1 *)
tempsize := fontsize;
i := 1;
WHILE TRUE DO BEGIN
(* Complete rest of fontspec starting at nxt
and return the position of first digit for fontsize.
We have to try fontsize +/- 1 before giving up because
rounding problems can occur in the above fontsize calculation.
*)
j := tempsize;
tempsizelen := 0;
WHILE j > 0 DO BEGIN
tempsizelen := tempsizelen + 1;
j := j DIV 10;
END;
IF NOT CompleteFontSpec(fontptr, nxt, tempsizelen, firstn) THEN
goto 999; (* fontspec truncated *)
lastn := firstn + tempsizelen - 1;
(* put tempsize into fontspec[firstn..lastn] *)
FOR j := lastn DOWNTO firstn DO BEGIN
fontspec[j] := CHR(ORD('0') + (tempsize MOD 10));
tempsize := tempsize DIV 10;
END;
IF i > 3 THEN (* original fontsize has been restored *)
goto 999; (* could not open fontspec *)
IF fontspeclen < maxstring THEN fontspec[fontspeclen] := CHR(0);
f := open(fontspec,O_RDONLY,0); (* try to open file *)
IF fontspeclen < maxstring THEN fontspec[fontspeclen] := ' ';
IF f >= 0 THEN BEGIN
result := close(f);
fontexists := TRUE; (* fontspec exists *)
goto 999;
END
ELSE IF i = 1 THEN
tempsize := fontsize - 1 (* try fontsize-1 *)
ELSE IF i = 2 THEN
tempsize := fontsize + 1 (* try fontsize+1 *)
ELSE
tempsize := fontsize; (* restore original fontsize *)
i := i + 1;
END;
END;
999:
END; (* BuildFontSpec *)
(******************************************************************************)
FUNCTION OpenFontFile (VAR name : string) : BOOLEAN;
(* Return TRUE if given file can be opened.
Only one font file will be open at any given time.
*)
LABEL 888;
VAR length : integer;
BEGIN
currPTbuff := -1; (* impossible value for first GetPTByte *)
length := 0;
WHILE length < maxstring DO BEGIN
IF name[length] = ' ' THEN goto 888;
length := length + 1;
END;
888:
IF length < maxstring THEN name[length] := CHR(0); (* terminate with NULL *)
PTfile := open(name, O_RDONLY, 0);
IF length < maxstring THEN name[length] := ' '; (* restore space *)
OpenFontFile := PTfile >= 0;
END; (* OpenFontFile *)
(******************************************************************************)
PROCEDURE CloseFontFile;
(* Close the currently open font file. *)
VAR result : integer;
BEGIN
result := close(PTfile);
END; (* CloseFontFile *)
(******************************************************************************)
FUNCTION GetPTByte : INTEGER;
(* Returns the value (unsigned) of the byte at PToffset and
advances PToffset for the next GetPTByte.
*)
VAR buffstart, result : INTEGER;
BEGIN
buffstart := (PToffset DIV bufflen) * bufflen; (* 0, bufflen, 2*bufflen... *)
IF buffstart <> currPTbuff THEN BEGIN
currPTbuff := buffstart;
result := lseek(PTfile, buffstart, 0);
{ DEBUG
IF result <> buffstart THEN BEGIN
writeln('Lseek failed in GetPTByte!'); RestoreTerminal; exit(1);
END;
GUBED }
result := read(PTfile, PTbuffer, bufflen);
{ DEBUG
IF result = -1 THEN BEGIN
writeln('Read failed in GetPTByte!'); RestoreTerminal; exit(1);
END;
GUBED }
END;
GetPTByte := ORD(PTbuffer[PToffset - buffstart]);
PToffset := PToffset + 1;
END; (* GetPTByte *)
(******************************************************************************)
FUNCTION SignedPTByte : INTEGER; (* the next byte, signed *)
VAR b : INTEGER;
BEGIN
b := GetPTByte;
IF b < 128 THEN
SignedPTByte := b
ELSE
SignedPTByte := b - 256;
END; (* SignedPTByte *)
(******************************************************************************)
FUNCTION GetTwoPTBytes : INTEGER; (* the next 2 bytes, unsigned *)
VAR a, b : INTEGER;
BEGIN
a := GetPTByte;
b := GetPTByte;
GetTwoPTBytes := a * 256 + b;
END; (* GetTwoPTBytes *)
(******************************************************************************)
FUNCTION SignedPTPair : INTEGER; (* the next 2 bytes, signed *)
VAR a, b : INTEGER;
BEGIN
a := GetPTByte;
b := GetPTByte;
IF a < 128 THEN
SignedPTPair := a * 256 + b
ELSE
SignedPTPair := (a - 256) * 256 + b;
END; (* SignedPTPair *)
(******************************************************************************)
FUNCTION GetThreePTBytes : INTEGER; (* the next 3 bytes, unsigned *)
VAR a, b, c : INTEGER;
BEGIN
a := GetPTByte;
b := GetPTByte;
c := GetPTByte;
GetThreePTBytes := (a * 256 + b) * 256 + c;
END; (* GetThreePTBytes *)
(******************************************************************************)
FUNCTION SignedPTQuad : INTEGER; (* the next 4 bytes, signed *)
TYPE int_or_bytes = RECORD
CASE b : BOOLEAN OF
TRUE : (int : INTEGER);
FALSE : (byt : PACKED ARRAY [0..3] OF CHAR);
END;
VAR w : int_or_bytes;
BEGIN
WITH w DO BEGIN
w.byt[0] := CHR(GetPTByte);
w.byt[1] := CHR(GetPTByte);
w.byt[2] := CHR(GetPTByte);
w.byt[3] := CHR(GetPTByte);
END;
SignedPTQuad := w.int;
END; (* SignedPTQuad *)
(******************************************************************************)
FUNCTION GetNyb : INTEGER;
(* Return next nybble in PK file. *)
BEGIN
IF bitweight = 0 THEN BEGIN
(* SYSDEP: Pyramid Pascal stores bits 7..0 in the LEFT
byte of a 4-byte BITSET word. *)
inputbyte.ch[0] := CHR(GetPTByte);
bitweight := 16; (* for next call of GetNyb *)
GetNyb := ORD(inputbyte.ch[0]) DIV 16; (* high nybble *)
END
ELSE BEGIN
bitweight := 0; (* for next call of GetNyb *)
GetNyb := ORD(inputbyte.ch[0]) MOD 16; (* low nybble *)
END;
END; (* GetNyb *)
(******************************************************************************)
FUNCTION PackedNum : INTEGER;
(* Return next run count using algorithm given in section 23 of PKtype.
A possible side-effect is to set the global repeatcount value used
to duplicate the current row.
*)
VAR i, j : INTEGER;
BEGIN
i := GetNyb;
IF i = 0 THEN BEGIN
REPEAT j := GetNyb; i := i + 1 UNTIL j <> 0;
WHILE i > 0 DO BEGIN j := j * 16 + GetNyb; i := i - 1 END;
PackedNum := j - 15 + (13 - dynf) * 16 + dynf;
END
ELSE IF i <= dynf THEN
PackedNum := i
ELSE IF i < 14 THEN
PackedNum := (i - dynf - 1) * 16 + GetNyb + dynf + 1
ELSE BEGIN
IF i = 14 THEN
repeatcount := PackedNum (* recursive *)
ELSE
repeatcount := 1; (* nybble = 15 *)
PackedNum := PackedNum; (* recursive *)
END;
END; (* PackedNum *)
(******************************************************************************)
PROCEDURE GetBitmap (ht, wd, mapadr : INTEGER; VAR bitmap : int_or_mptr);
(* Allocate space for bitmap and fill it in using information from
character definition starting at mapadr in currently open PK file.
Note that the memory used by a loaded bitmap is never deallocated.
Each bitmap row uses an integral number of words (each 32 bits).
Byte-aligned rows would use about 35% less memory but
would increase the processing time needed to display each bitmap.
It was felt that speed is more important than memory.
*)
VAR
wordptr, rowptr : int_or_bptr;
i, j, flagbyte,
wordwidth, wordweight,
rowsleft, hbit, count, bitmapwords : INTEGER;
word : BITSET;
bitmapptr : bitmap_ptr;
BEGIN
wordwidth := (wd + 31) DIV 32; (* words in one row of bitmap *)
bitmapwords := ht * wordwidth; (* memory required by bitmap *)
{ DEBUG
IF bitmapwords > large_size THEN WriteChar(CHR(7)); (* bell *)
GUBED }
IF bitmapwords <= small_size THEN
NEW(bitmapptr,small)
ELSE IF bitmapwords <= big_size THEN
NEW(bitmapptr,big)
ELSE IF bitmapwords <= large_size THEN
NEW(bitmapptr,large)
ELSE IF bitmapwords <= huge_size THEN
NEW(bitmapptr,huge)
ELSE BEGIN
WriteString('Character too big! size=');
WriteInt(bitmapwords); WriteLine; RestoreTerminal; exit(1);
END;
bitmap.mptr := bitmapptr; (* return start of bitmap *)
wordptr.int := bitmap.int;
PToffset := mapadr; (* mapadr = flagbyte offset in PK file *)
flagbyte := GetPTByte; (* assume < 240 *)
dynf := flagbyte DIV 16; (* dynamic packing variable *)
turnon := (flagbyte MOD 16) >= 8; (* is 1st pixel black? *)
flagbyte := flagbyte MOD 8; (* value of bottom 3 bits *)
IF flagbyte < 4 THEN (* skip short char preamble *)
PToffset := PToffset + 10
ELSE IF flagbyte < 7 THEN (* skip extended short char preamble *)
PToffset := PToffset + 16
ELSE (* skip long char preamble *)
PToffset := PToffset + 36;
bitweight := 0; (* to get 1st inputbyte *)
IF dynf = 14 THEN BEGIN
(* raster info is a string of bits in the next (wd * ht + 7) DIV 8 bytes *)
FOR i := 1 TO ht DO BEGIN
word := []; (* set all bits to 0 *)
wordweight := 31; (* leftmost bit *)
FOR j := 1 TO wd DO BEGIN
IF bitweight = 0 THEN BEGIN
(* SYSDEP: Pyramid Pascal stores bits 7..0 in the LEFT
byte of a 4-byte BITSET word. *)
inputbyte.ch[0] := CHR(GetPTByte);
bitweight := 8;
END;
bitweight := bitweight - 1; (* 7..0 *)
IF bitweight IN inputbyte.bits THEN
word := word + [wordweight]; (* set bit *)
IF wordweight > 0 THEN
wordweight := wordweight - 1
ELSE BEGIN
wordptr.bptr^ := word;
wordptr.int := wordptr.int + 4;
word := []; wordweight := 31;
END;
END;
IF wordweight < 31 THEN BEGIN
wordptr.bptr^ := word;
wordptr.int := wordptr.int + 4; (* start of next word *)
END;
END;
END
ELSE BEGIN
(* raster info is encoded as run and repeat counts *)
rowsleft := ht; hbit := wd; repeatcount := 0;
wordweight := 32; word := [];
rowptr := wordptr; (* remember start of row *)
WHILE rowsleft > 0 DO BEGIN
count := PackedNum;
WHILE count > 0 DO BEGIN
IF (count < wordweight) AND (count < hbit) THEN BEGIN
IF turnon THEN
word := word + gpower[wordweight] - gpower[wordweight - count];
hbit := hbit - count;
wordweight := wordweight - count;
count := 0;
END
ELSE IF (count >= hbit) AND (hbit <= wordweight) THEN BEGIN
IF turnon THEN
word := word + gpower[wordweight] - gpower[wordweight - hbit];
wordptr.bptr^ := word;
(* end of current row, so duplicate repeatcount times *)
FOR i := 1 TO repeatcount DO
FOR j := 1 TO wordwidth DO BEGIN
wordptr.int := wordptr.int + 4;
wordptr.bptr^ := rowptr.bptr^;
rowptr.int := rowptr.int + 4;
END;
rowsleft := rowsleft - (repeatcount + 1);
repeatcount := 0;
word := [];
wordptr.int := wordptr.int + 4;
rowptr := wordptr; (* remember start of next row *)
wordweight := 32;
count := count - hbit;
hbit := wd;
END
ELSE BEGIN
IF turnon THEN word := word + gpower[wordweight];
wordptr.bptr^ := word;
wordptr.int := wordptr.int + 4;
word := [];
count := count - wordweight;
hbit := hbit - wordweight;
wordweight := 32;
END;
END;
turnon := NOT turnon;
END;
END;
END; (* GetBitmap *)
(******************************************************************************)
FUNCTION FixToDVI (b0, b1, b2, b3 : INTEGER) : INTEGER;
(* Convert the given fix width (made up of 4 bytes) into DVI units
using the method recommended in DVITYPE.
*)
VAR alpha, beta, temp : INTEGER;
BEGIN
WITH currfont^ DO BEGIN
alpha := 16 * scaledsize;
beta := 16;
WHILE scaledsize >= 8#40000000 DO BEGIN (* 2^23 *)
scaledsize := scaledsize DIV 2;
beta := beta DIV 2;
END;
temp := (((((b3 * scaledsize) DIV 8#400) +
(b2 * scaledsize)) DIV 8#400) +
(b1 * scaledsize)) DIV beta;
IF b0 > 0 THEN
IF b0 = 255 THEN
FixToDVI := temp - alpha
ELSE BEGIN
WriteString('Bad TFM width! 1st byte='); WriteInt(b0);
WriteLine; RestoreTerminal; exit(1);
END
ELSE
FixToDVI := temp;
END;
END; (* FixToDVI *)
(******************************************************************************)
PROCEDURE PKFillPixelTable;
(* Fill the pixeltable for currfont^ using the font directory info
in the currently open PK file.
*)
LABEL 888;
CONST
pkid = 89;
pkpost = 245;
pknoop = 246;
pkpre = 247;
VAR
i, j, flagbyte, flagpos,
chcode, (* assumed to be <= 255 *)
packetlen, endofpacket,
b0, b1, b2, b3 : INTEGER; (* 4 bytes in TFM width *)
BEGIN
WITH currfont^ DO BEGIN
PToffset := 0; (* move to first byte *)
IF GetPTByte <> pkpre THEN BEGIN
WriteString('Bad pre command in'); WriteChar(' ');
WriteString(fontspec); WriteLine; RestoreTerminal; exit(1);
END;
IF GetPTByte <> pkid THEN BEGIN
WriteString('Bad id byte in'); WriteChar(' ');
WriteString(fontspec); WriteLine; RestoreTerminal; exit(1);
END;
j := GetPTByte; (* length of comment *)
PToffset := PToffset + j + 16; (* skip rest of preamble *)
FOR i := 0 TO maxTeXchar DO
WITH pixelptr^[i] DO BEGIN
mapadr := 0; (* all chars absent initially *)
bitmap.mptr := NIL;
END;
WHILE TRUE DO BEGIN
flagpos := PToffset; (* remember position of flagbyte *)
flagbyte := GetPTByte;
IF flagbyte < 240 THEN BEGIN (* read character definition *)
flagbyte := flagbyte MOD 8; (* value of bottom 3 bits *)
IF flagbyte < 4 THEN BEGIN (* short char preamble *)
packetlen := flagbyte * 256 + GetPTByte;
chcode := GetPTByte;
endofpacket := packetlen + PToffset;
WITH pixelptr^[chcode] DO BEGIN
b1 := GetPTByte;
b2 := GetPTByte;
b3 := GetPTByte;
dwidth := FixToDVI(0,b1,b2,b3); (* b0 = 0 *)
pwidth := GetPTByte;
wd := GetPTByte;
ht := GetPTByte;
xo := SignedPTByte;
yo := SignedPTByte;
END;
END
ELSE IF flagbyte < 7 THEN BEGIN (* extended short char preamble *)
packetlen := (flagbyte - 4) * 65536 + GetTwoPTBytes;
chcode := GetPTByte;
endofpacket := packetlen + PToffset;
WITH pixelptr^[chcode] DO BEGIN
b1 := GetPTByte;
b2 := GetPTByte;
b3 := GetPTByte;
dwidth := FixToDVI(0,b1,b2,b3); (* b0 = 0 *)
pwidth := GetTwoPTBytes;
wd := GetTwoPTBytes;
ht := GetTwoPTBytes;
xo := SignedPTPair;
yo := SignedPTPair;
END;
END
ELSE BEGIN (* long char preamble *)
packetlen := SignedPTQuad;
chcode := SignedPTQuad;
endofpacket := packetlen + PToffset;
WITH pixelptr^[chcode] DO BEGIN
b0 := GetPTByte;
b1 := GetPTByte;
b2 := GetPTByte;
b3 := GetPTByte;
dwidth := FixToDVI(b0,b1,b2,b3);
pwidth := SignedPTQuad DIV 65536; (* dx in pixels *)
PToffset := PToffset + 4; (* skip dy *)
wd := SignedPTQuad;
ht := SignedPTQuad;
xo := SignedPTQuad;
yo := SignedPTQuad;
END;
END;
WITH pixelptr^[chcode] DO
IF (wd = 0) OR (ht = 0) THEN
mapadr := 0 (* no bitmap *)
ELSE
mapadr := flagpos; (* position of flagbyte *)
PToffset := endofpacket; (* skip raster info *)
END
ELSE
CASE flagbyte OF
240, 241, 242, 243 :
BEGIN
i := 0;
FOR j := 240 TO flagbyte DO i := 256 * i + GetPTByte;
PToffset := PToffset + i; (* skip special parameter *)
END;
244 : PToffset := PToffset + 4; (* skip numspecial param *)
pknoop : ; (* do nothing *)
pkpost : goto 888; (* no more char defs *)
OTHERWISE
WriteString('Bad flag byte in'); WriteChar(' ');
WriteString(fontspec); WriteLine; RestoreTerminal; exit(1);
END;
END; (* of LOOP; flagbyte = pkpost *)
888:
END;
END; (* PKFillPixelTable *)
(******************************************************************************)
PROCEDURE ReadTFMIntegers;
(* Read the first 6 16-bit integers in the TFM file. See TFtoPL section 8. *)
BEGIN
PToffset := 0; (* start reading at 1st byte in TFM file *)
lf := GetTwoPTBytes;
lh := GetTwoPTBytes;
bc := GetTwoPTBytes;
ec := GetTwoPTBytes;
nw := GetTwoPTBytes;
nh := GetTwoPTBytes;
END; (* ReadTFMIntegers *)
(******************************************************************************)
PROCEDURE ReadTFMCharInfo;
(* Read the TFMinfo array. See TFtoPL section 11. *)
VAR c, i : INTEGER;
BEGIN
PToffset := 24 + (lh * 4); (* offset of TFMinfo array *)
FOR c := bc TO ec DO
WITH TFMinfo[c] DO BEGIN
wdindex := GetPTByte * 4; (* offset from start of width array *)
i := GetPTByte; (* 2nd byte contains htindex and dpindex *)
htindex := (i DIV 16) * 4; (* offset from start of height array *)
dpindex := (i MOD 16) * 4; (* offset from start of depth array *)
PToffset := PToffset + 2; (* skip itindex and remainder bytes *)
END;
END; (* ReadTFMCharInfo *)
(******************************************************************************)
PROCEDURE ReadTFMCharMetrics;
(* Read the charmetrics array using the indices in TFMinfo. *)
VAR wdbase, htbase, dpbase, b, c : INTEGER;
BEGIN
wdbase := 24 + lh * 4 + (ec - bc + 1) * 4; (* offset of width array *)
htbase := wdbase + nw * 4; (* offset of height array *)
dpbase := htbase + nh * 4; (* offset of depth array *)
FOR c := bc TO ec DO
WITH TFMinfo[c] DO
WITH charmetrics[c] DO BEGIN
PToffset := wdbase + wdindex;
FOR b := 0 TO 3 DO width[b] := GetPTByte;
PToffset := htbase + htindex;
FOR b := 0 TO 3 DO height[b] := GetPTByte;
PToffset := dpbase + dpindex;
FOR b := 0 TO 3 DO depth[b] := GetPTByte;
END;
END; (* ReadTFMCharMetrics *)
(******************************************************************************)
PROCEDURE TFMFillPixelTable;
(* Fill the pixeltable for currfont^ (a PostScript font)
using information in the currently open TFM file.
*)
VAR c, dheight, pheight, ddepth, pdepth : INTEGER;
BEGIN
ReadTFMIntegers; (* read lf..nh *)
ReadTFMCharInfo; (* fill TFMinfo array *)
ReadTFMCharMetrics; (* fill charmetrics array *)
WITH currfont^ DO BEGIN
FOR c := 0 TO bc - 1 DO
pixelptr^[c].mapadr := 0; (* chars < bc don't exist *)
FOR c := ec + 1 TO 255 DO
pixelptr^[c].mapadr := 0; (* chars > ec don't exist *)
FOR c := bc TO ec DO
WITH pixelptr^[c] DO
WITH charmetrics[c] DO BEGIN
dwidth := FixToDVI(width[0],width[1],width[2],width[3]);
dheight := FixToDVI(height[0],height[1],height[2],height[3]);
ddepth := FixToDVI(depth[0],depth[1],depth[2],depth[3]);
(* convert DVI units to pixels *)
pwidth := PixelRound(dwidth);
pheight := PixelRound(dheight);
pdepth := PixelRound(ddepth);
(* Since we don't have access to bitmap info for a PostScript font
we will have to use the TFM width/height/depth info to
approximate wd, ht, xo, yo.
*)
wd := pwidth;
wd := wd - (wd DIV 8); (* better approximation *)
ht := pheight + pdepth;
xo := 0;
yo := pheight - 1;
IF (wd = 0) OR (ht = 0) THEN
mapadr := 0 (* char all-white or not in font *)
ELSE
mapadr := 1; (* anything but 0 *)
bitmap.mptr := NIL;
END;
END;
END; (* TFMFillPixelTable *)
(******************************************************************************)
PROCEDURE PixelTableRoutine;
(* DVIReader has just allocated a new pixeltable for currfont^ and
calls this routine from InterpretPage only ONCE per font
(the first time the font is used).
If this is the first time we've seen the font then we build fontspec first.
(Note that ShowStatistics in the main program may call BuildFontSpec first.)
If we can't open the font file we return dummyfont values, but using the
current font's scaledsize.
*)
VAR ch : CHAR;
BEGIN
WITH currfont^ DO BEGIN
IF fontspeclen = 0 THEN BuildFontSpec(currfont);
IF OpenFontFile(fontspec) THEN BEGIN
{ DEBUG
ClearTextLine(messagel);
MoveToTextLine(messagel);
WriteString('Loading font data from'); WriteChar(' ');
WriteString(fontspec);
WriteLine;
GUBED }
END
ELSE IF OpenFontFile(dummyfont) THEN BEGIN
(* we will fill pixeltable with dummyfont values *)
ClearTextLine(messagel);
MoveToTextLine(messagel);
WriteString('Couldn''t open'); WriteChar(' '); WriteString(fontspec);
WriteString('! Loading dummy font.');
WriteString(' RETURN:');
WriteBuffer;
REPEAT ReadChar(ch) UNTIL ch = CR;
ClearTextLine(messagel);
MoveToTextLine(messagel);
WriteBuffer;
END
ELSE BEGIN
ClearTextLine(messagel);
MoveToTextLine(messagel);
WriteString('Couldn''t open dummy font'); WriteChar(' ');
WriteString(dummyfont); WriteLine; RestoreTerminal; exit(1);
END;
IF psfont AND fontexists THEN
TFMFillPixelTable
ELSE
PKFillPixelTable;
CloseFontFile;
END;
END; (* PixelTableRoutine *)
(******************************************************************************)
PROCEDURE InitFontReader;
(* This routine initializes some global variables. *)
VAR i : INTEGER;
BEGIN
gpower[0] := [];
FOR i := 1 TO 32 DO gpower[i] := gpower[i-1] + [i-1]; (* used in GetBitmap *)
psprefixlen := Len(psprefix);
fontdirlen := Len(fontdir);
END; (* InitFontReader *)